/**
 * 内核所用的通用链表
 * 主要用于组织任务，一些事件等
*/
#ifndef OS_LIST_H
#define OS_LIST_H

#include "os_err.h"
#include "os_plat.h"
#include "os_dbg.h"
#include "os_def.h"

/**
 * 链表结点，可放置于任何结构中
*/
typedef struct _os_list_item_t {
    struct _os_list_item_t * pre;               // 前一结点
    struct _os_list_item_t * next;              // 后一结点

    // 下面的这些方便调试
#if OS_LIST_INFO_ENABLE
    union {
        void * owner;
    }owner;
#endif // OS_DEBUG_ENABLE
}os_list_item_t;

void __os_list_item_init (os_list_item_t * item, int offset);
#define os_list_item_init(item, owner_type, link_name)  __os_list_item_init(item, (int)((char *)&(((owner_type*)0)->link_name)))


/**
 * 内核链表
 * 采用双向链表结构
*/
typedef struct _os_list_t {
    os_list_item_t * first;             // 首个结点
    os_list_item_t * last;              // 尾结点
	uint16_t count;                          // 结点数量
	uint16_t owner_offset;                   // 容量相对item的偏移量
}os_list_t;

/**
 * 初始化队列
 */
void __os_list_init (os_list_t * list, int owner_offset);
#define os_list_init(list, owner_type, link_name)    __os_list_init(list, (int)((char *)&(((owner_type*)0)->link_name)))

/**
 * 返回任务列表中结点的数量
 * @param list 任务列表
 * @return 任务数量
 */
static inline int os_list_count (os_list_t * list) {
    os_assert(list != OS_NULL);
	return list->count;
}

void * os_list_item_next (os_list_t * list, void * obj);
void * os_list_item_pre (os_list_t * list, void * obj);
void * os_list_first (os_list_t * list);
void * os_list_last (os_list_t * list);
void os_list_insert_first (os_list_t * list, void * obj);
void * os_list_remove_first (os_list_t * list);
void os_list_insert_last (os_list_t * list, void * obj);
void os_list_insert_after (os_list_t * list, void * pre_obj, void * next_obj);
void os_list_remove_item (os_list_t * list, void * obj);
void os_list_remove_all (os_list_t * list);

/**
 * 用于链表辅助遍历的函数
*/
#define os_list_for_each(obj, owner_type, list)     \
    owner_type * obj;                     \
    for (obj = (owner_type *)os_list_first(list); obj; obj = (owner_type *)os_list_item_next(list, obj))     


#if OS_LIST_INFO_ENABLE
void os_list_check (os_list_t * list);
#else
#define os_list_check(list)
#endif

#endif /* TLIB_H */
